/**
 * Webpack loader for generating simple ES modules that aggregate and
 * re-export other modules.
 *
 * The power behind [TargetableESModuleArray][].
 */
const defaultExportRE = /^\s*export\s+default\s+(\[[\s\n]*\]|\{[\s\n]*\});?/m;
const defaultExportStartsWith = (content, char) => {
    const exportMatch = content.match(defaultExportRE);
    return exportMatch && exportMatch[1].charAt(0) === char;
};

function exportEsmCollectionLoader(content) {
    const { bindings, type, errors = [] } = this.query[0];
    const [open, close] = type === 'array' ? ['[', ']'] : ['{', '}'];

    if (!defaultExportStartsWith(content, open)) {
        this.emitError(
            new Error(
                `items provided as ${type}, but cannot export an ${type} because template module "${
                    this.resourcePath
                }" does not export an empty ${type}.
            Note that comments are not allowed between the ${open} and ${close} for these template modules, but should be placed above the export declaration.

            Contents of "${this.resourcePath}":
            ${content}`
            )
        );
        return content;
    }

    if (bindings.length === 0) {
        this.emitWarning(
            new Error(`Bindings array was empty; no changes will be made`)
        );
        return content;
    }

    // When type is `object`, it's possible to cause an error by overwriting a
    // prexisting property. Emit those errors here.
    errors.forEach(error => this.emitError(new Error(error)));

    // Leave any stuff in the file that is above the default export.
    const preamble = content.replace(defaultExportRE, '');
    const explanatory = `// generated by export-esm-collection-loader`;
    const exportList = bindings.join(',\n  ');

    return `${preamble}${explanatory}\n\nexport default ${open}\n  ${exportList}\n${close};`;
}

module.exports = exportEsmCollectionLoader;
